/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.utils;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.ui.IActionFilter;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Profile;

import com.cea.papyrus.core.editpart.IUMLElementEditPart;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;


/**
 * 
 * this class is used do add add a filter to design a customized palette
 * 
 */
public class UMLObjectActionFilter implements IActionFilter {
	
	/**
	 * filter to test the uml type
	 */
	public final static String ATT_UMLType		= "isUmlType";
	
	/**
	 *filter to test is the root 
	 */
	public final static String ATT_UMLRoot		= "isRootPackage";
	
	/**
	 * filter tanks to Diagram type 
	 */
	public final static String ATT_DiagramType	= "isDiagramType";
	
	/**
	 * filter is stereotype
	 */
	public final static String ATT_Stereotype	= "hasStereotype";
	
	/**
	 * this method is used to test if the element repects our constraint
	 * for example
	 * {@code boolean isClass = testAttribute(object, ATT_UMLType, "Class");}
	 * declares that we test that the object is a class 
	 * @param value of the filter
	 * @param target the objet that will be the parent of our future element
	 * @param name kind of test
	 * 
	 * @return true is the test is true
	 */
	public boolean testAttribute(Object target, String name, String value) {
		Object _target = target;
		if (target instanceof IUMLElementEditPart) {
			_target = ((IUMLElementEditPart) target).getUmlElement();
		}
		
		// Testing uml type
		if (UMLObjectActionFilter.ATT_UMLType.equals(name)) {
			
			return testAttributeUmlType(_target, value);
		}
		
		// Testing isRootPackage
		if (UMLObjectActionFilter.ATT_UMLRoot.equals(name)) {
			
			return testAttributeRoot(_target);
		}		
		
		// Testing diagram type
		if (UMLObjectActionFilter.ATT_DiagramType.equals(name)) {
			
			return testAttributeDiagramType(_target, value);
		}
		
		// Testing applied stereotype
		if (UMLObjectActionFilter.ATT_Stereotype.equals(name)) {
			
			return testAttributeHasStereotype(_target, value);
		}
		
		// For anything else
		return false;
	}
	
	/**
	 * Test if target object is a uml object from type value
	 * Exception if value is "RootPackage" :
	 * - test if type is Package and is root object (either model or profile).
	 * 
	 * @param value 
	 * @param target 
	 * 
	 * @return 
	 */
	private boolean testAttributeUmlType(Object target, String value) {

		if (! (target instanceof Element)) {
			return false;
		}
		
		try {
			Class t = Class.forName("org.eclipse.uml2.uml."+value);

			if (t.isInstance(target)) {
				return true;
			}

		} catch (Exception e) {
			Debug.log(IStatus.ERROR, "No class found with this name : org.eclipse.uml2.uml."+value);
		}

		// For anything else
		return false;
	}
	
	/**
	 * Test if target object is a Diagram which type is value.
	 * 
	 * @param value 
	 * @param target 
	 * 
	 * @return 
	 */
	private boolean testAttributeDiagramType(Object target, String value) {

		if (! (target instanceof Diagram)) {
			return false;
		}

		Diagram dTarget = (Diagram) target;

		if (value.equals(dTarget.getType())) {
			return true;
		}
		
		// For everything else
		return false;
	}
	
	/**
	 * Test if current target is a Uml element and has the stereotype
	 * value (value is its name) applied.
	 * 
	 * @param value 
	 * @param target 
	 * 
	 * @return 
	 */
	private boolean testAttributeHasStereotype(Object target, String value) {

		if ( ! (target instanceof Element)) {
			return false;
		}
		
		com.cea.papyrus.umlutils.Element targetElement = new com.cea.papyrus.umlutils.Element((Element) target);
		
		if (targetElement.hasStereotype(value)) {				
			return true;
		}

		// For anything else
		return false;
	}
	
	/**
	 * Test if target object is the Root uml package.
	 * 
	 * @param value 	
	  * @param target 
	 * 
	 * @return 
	 */
	private boolean testAttributeRoot(Object target) {

		if ( !(target instanceof Model)
				&& !(target instanceof Profile)) {
			return false;
		}
		
		Package targetPkg = (Package) target; 
		if (targetPkg.getOwner() == null) {
			return true;
		}


		// For anything else
		return false;
	}
}
